{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to Vcc Glitch Attacks\n",
    "\n",
    "Supported setups:\n",
    "\n",
    "SCOPES:\n",
    "\n",
    "* OPENADC\n",
    "\n",
    "PLATFORMS:\n",
    "\n",
    "* CWLITEARM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SCOPETYPE = 'OPENADC'\n",
    "PLATFORM = 'CWLITEARM'\n",
    "sample_size = 5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Background on Vcc (Power) Glitching"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The previous clock glitching tutorials looked into the assumption of a constant clock. But instead we can modify the voltage of the device, causing for example a failure to correctly read a memory location or otherwise cause havoc with the proper functioning.\n",
    "\n",
    "An example of a successful Vcc glitch is shown in the following figures (Vcc in blue, clock in red):\n",
    "\n",
    "![](https://wiki.newae.com/images/4/4f/Vccglitch_working.png)\n",
    "\n",
    "![](https://wiki.newae.com/images/6/60/Vccglitch_working_zoom.png)\n",
    "\n",
    "Even more so than clock glitching, Vcc glitching is highly sensitive to glitch offset and width. While the above glitch was successful, the following was not:\n",
    "\n",
    "![](https://wiki.newae.com/images/b/b6/Vccglitch_notworking_zoom.png)\n",
    "\n",
    "Vcc glitching is also very sensitive to the shape of the glitch: things like board layout and the distance between where the glitch is inserted and the target can make the difference between successful and unsuccessful glitches.\n",
    "\n",
    "Despite these additional complications, Vcc glitching is an extremely useful tool as it allows attacks on targets that do not run off of external clock inputs."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Background on Glitch Generation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For more details, please see [Fault_1-Introduction_to_Clock_Glitching](Fault_1-Introduction_to_Clock_Glitch_Attacks.ipynb), this tutorials assumes you have already performed the clock glitching tutorial.\n",
    "\n",
    "The glitch generation hardware is the same as used in the clock glitching attack. The generated glitches are synchronous to the device clock, and inserted at a precise offset from the clock edge.\n",
    "\n",
    "Glitches can be inserted continuously or triggered by some event. The following figure shows the generation of two glitches:\n",
    "\n",
    "![](https://wiki.newae.com/images/9/95/Glitchgen-mux-glitchonly.png)\n",
    "\n",
    "The VCC glitching method here uses an electronic switch (a MOSFET) to short the power line to GND at specific instances. The following figure shows the basic function of this system:\n",
    "\n",
    "![](https://wiki.newae.com/images/8/82/Glitch-vccglitcher.png)\n",
    "\n",
    "This method allows use with the standard side-channel analysis development board, which has resistors inserted into the VCC lines already. The downside of this method is that it can only generate short glitches, since the power consumption through the shunt resistor will short out the resistor.\n",
    "\n",
    "The MOSFET glitching hardware is built into the ChipWhisperer-Lite (both CW1173 and CW1180) board."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setting up Firmware"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "During this tutorial, we will once again be working off the `glitch-simple` project."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now navigate to the `glitch-simple` folder and open `glitchsimple.c` in a code editor. Find the `glitch_infinite()` function:\n",
    "\n",
    "```C\n",
    "void glitch_infinite(void)\n",
    "{\n",
    "    char str[64];\n",
    "    unsigned int k = 0;\n",
    "    //Declared volatile to avoid optimizing away loop.\n",
    "    //This also adds lots of SRAM access\n",
    "    volatile uint16_t i, j;\n",
    "    volatile uint32_t cnt;\n",
    "    while(1){\n",
    "        cnt = 0;\n",
    "        trigger_high();\n",
    "        trigger_low();\n",
    "        for(i=0; i<200; i++){\n",
    "            for(j=0; j<200; j++){\n",
    "                cnt++;\n",
    "            }\n",
    "        }\n",
    "        sprintf(str, \"%lu %d %d %d\\n\", cnt, i, j, k++);\n",
    "        uart_puts(str);\n",
    "    }\n",
    "}\n",
    "```\n",
    "\n",
    "As you can see, this function enters into an infinite loop with two inner loops that increment three variables (`cnt`, `i`, and `j`).  These are sent back over serial along with an overall loop counter. During normal operation, we should receive `40000 200 200 $k` (where `$k` is the value of the loop counter `k`). Our objective will be to insert a Vcc glitch such that one or more of the numbers that we get back are incorrect."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then build the firmware:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash -s \"$PLATFORM\"\n",
    "cd ../hardware/victims/firmware/glitch-simple\n",
    "make PLATFORM=$1 CRYPTO_TARGET=NONE FUNC_SEL=GLITCH_INF"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Attack Script"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we've studied the code and have an objective, we can start building our attack script. We'll start by connecting to and setting up the ChipWhisperer, then programming it. As usual, make sure you modify `fw_path` with the path to the file you built in the last step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%run \"Helper_Scripts/Setup_Generic.ipynb\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fw_path = \"../hardware/victims/firmware/glitch-simple/glitchsimple-{}.hex\".format(PLATFORM)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cw.program_target(scope, prog, fw_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Like with clock glitching, Vcc glitching may crash the target, requiring a reset. Like with the previous tutorial, we'll use `reset_target()` from `Helper_Scripts/Setup.ipynb`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we have some of the basic setup done, let's make sure the firmware works as we expect. If we reset the target and wait a second, then print the serial data we got back, we should see a number of lines of the form `40000 200 200 $k`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "reset_target(scope)\n",
    "target.flush()\n",
    "time.sleep(1)\n",
    "resp = target.read()\n",
    "print(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Glitch Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we'll setup the glitch module itself. Most of these settings should look familiar from the previous tutorial with a few new additions:\n",
    "\n",
    "* Instead of setting the clock source for the target to be the glitch module, we instead set one of the ChipWhisperer's glitch MOSFETs as our glitch by setting `scope.io.glitch_lp` or `scope.io.glitch_hp` to `True`.\n",
    "    * Depending on your hardware setup, you may find that one MOSFET works better than the other. If you have trouble glitching the target with one, try the other\n",
    "* Instead of setting the glitch output to something like \"clock_xor\", we instead set it to \"glitch_only\", since we don't want Vcc of the target to be oscillating with our clock.\n",
    "\n",
    "For the more specific settings (offset, width, repeat, etc), this will depend on both the target and when you got your CW-Lite: Newer versions of the CW-Lite use a different LP glitch MOSFET, which changes the settings required for getting a glitch."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import namedtuple\n",
    "Range = namedtuple('Range', ['min', 'max', 'step'])\n",
    "if PLATFORM == \"CWLITEARM\" or PLATFORM == \"CW308_STM32F3\":\n",
    "    scope.glitch.clk_src = \"clkgen\"\n",
    "    scope.glitch.output = \"glitch_only\"\n",
    "    scope.glitch.trigger_src = \"ext_single\"\n",
    "    \n",
    "    width_range = Range(28, 30, 0.4)\n",
    "    offset_range = Range(-25, -18, 0.4)\n",
    "    ext_range = range(1000, 1005)\n",
    "    \n",
    "    scope.glitch.width = width_range.min\n",
    "    scope.glitch.offset = offset_range.min\n",
    "    scope.glitch.repeat = 1\n",
    "    def glitch_on(scope):\n",
    "        scope.io.glitch_lp = False\n",
    "        scope.io.glitch_hp = True\n",
    "    def glitch_off(scope):\n",
    "        scope.io.glitch_hp = False\n",
    "    glitch_on(scope)\n",
    "    scope.glitch.ext_offset = 1000\n",
    "    print(scope.glitch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(scope)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Glitching a Single Point"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Unlike with the previous tutorial, we don't control when the device sends serial data back to us. This means we'll need to parse the data we get back."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We start our attack off by flushing the ChipWhipserer's serial buffer:\n",
    "\n",
    "```Python\n",
    "target.flush()\n",
    "```\n",
    "\n",
    "Next, we'll set our trigger source to be \"ext_continuous\". This differs from \"ext_single\" in that the ChipWhisperer doesn't need to be armed to insert a glitch, making our loop a little simpler:\n",
    "\n",
    "```Python\n",
    "scope.glitch.trigger_src = \"ext_continuous\"\n",
    "```\n",
    "\n",
    "A key part of parsing the serial data is to be able to read a line of data (data terminated with \"\\n\"). We can do that by reading back data until we get a newline character (\"\\n\"):\n",
    "\n",
    "```Python\n",
    "while \"\\n\" not in line:\n",
    "    time.sleep(0.1)\n",
    "    line += target.read()\n",
    "```\n",
    "\n",
    "This needs to be repeated twice in our loop: once at the start to make sure we're on a newline (so we don't look at the wrong numbers for our glitch) and again to actually read the line. For the first read, we also need to make sure we keep any characters after the newline, as this will be the start of the actual line we parse. All together, this looks like:\n",
    "\n",
    "```Python\n",
    "line = \"\"\n",
    "while \"\\n\" not in line:\n",
    "    time.sleep(0.1)\n",
    "    line += target.read()\n",
    "lines = line.split(\"\\n\") \n",
    "if len(lines) > 1:\n",
    "    line = lines[-1]\n",
    "else:\n",
    "    line = \"\"\n",
    "\n",
    "while \"\\n\" not in line:\n",
    "    time.sleep(0.1)\n",
    "    line += target.read(num_char)\n",
    "```\n",
    "\n",
    "Now that we have our line of data we can parse it by splitting it up via spaces to get each number. \n",
    "\n",
    "After the loop ends, we'll need to set our trigger back to \"ext_single\" to stop the glitches from continuing.\n",
    "\n",
    "All together (with some additional error checking), this looks like:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm import tnrange\n",
    "reset_target(scope)\n",
    "target.flush()\n",
    "\n",
    "if SCOPETYPE == \"OPENADC\":\n",
    "    scope.glitch.trigger_src = \"ext_continuous\"\n",
    "\n",
    "for j in tnrange(20):\n",
    "    line = \"\"\n",
    "    \n",
    "    while \"\\n\" not in line:\n",
    "        time.sleep(0.1)\n",
    "        line += target.read()\n",
    "    lines = line.split(\"\\n\") \n",
    "    if len(lines) > 1:\n",
    "        line = lines[-1]\n",
    "    else:\n",
    "        line = \"\"\n",
    "    \n",
    "    while \"\\n\" not in line:\n",
    "        time.sleep(0.1)\n",
    "        line += target.read()\n",
    "        \n",
    "    if \"hello\" in line:\n",
    "        print(\"Target crashed\")\n",
    "    nums = line.split(\" \")\n",
    "    try:\n",
    "        if int(nums[0]) != 40000:\n",
    "            print(line)\n",
    "        print(line)\n",
    "    except ValueError as e:\n",
    "        continue\n",
    "\n",
    "if SCOPETYPE == \"OPENADC\":\n",
    "    scope.glitch.trigger_src = \"ext_single\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should hopefully see some glitched lines printed after running the above block. If not, don't worry -- we'll be adjusting the settings of the glitch which should make them more likely."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Improving Glitch Settings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One more thing we can do to improve our glitch success rate is to modify our glitch settings (width and offset) while holding the ext offset constant. \n",
    "\n",
    "Similar to [Fault_1](Fault_1-Introduction_to_Clock_Glitch_Attacks.ipynb), let's also measure our success rate with each glitch setting, as well as our crash rate, then print them at the end.\n",
    "\n",
    "To keep things a little more sane, let's put our glitch attempt into a function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def do_glitch():\n",
    "    global scope, target\n",
    "    line = \"\"\n",
    "    while \"\\n\" not in line:\n",
    "        time.sleep(0.1)\n",
    "        num_char = target.in_waiting()\n",
    "        if num_char == 0:\n",
    "            glitch_off(scope)\n",
    "            time.sleep(0.01)\n",
    "            glitch_on(scope)\n",
    "            break\n",
    "        line += target.read()\n",
    "    lines = line.split(\"\\n\") \n",
    "    if len(lines) > 1:\n",
    "        line = lines[-1]\n",
    "    else:\n",
    "        line = \"\"\n",
    "\n",
    "    while \"\\n\" not in line:\n",
    "        time.sleep(0.1)\n",
    "        num_char = target.in_waiting()\n",
    "        if num_char == 0:\n",
    "            glitch_off(scope)\n",
    "            time.sleep(0.01)\n",
    "            glitch_on(scope)\n",
    "            break\n",
    "        line += target.read()\n",
    "\n",
    "    nums = line.split(\" \")\n",
    "    crashes=0\n",
    "    if \"hello\" in line:\n",
    "        crashes = 1\n",
    "    successes = 0\n",
    "    try:\n",
    "        if nums[0] == \"\":\n",
    "            pass\n",
    "        if int(nums[0]) != 40000:\n",
    "            successes = 1\n",
    "    except ValueError as e:\n",
    "        pass\n",
    "    return successes, crashes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we can run the actual loop that iterates through all our settings:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm import tnrange, tqdm_notebook\n",
    "reset_target(scope)\n",
    "glitches = []\n",
    "glitch_text = []\n",
    "\n",
    "target.flush()\n",
    "scope.glitch.trigger_src = \"ext_continuous\"\n",
    "scope.glitch.offset_fine = 0\n",
    "scope.glitch.repeat = 1\n",
    "scope.glitch.ext_offset = 1000\n",
    "scope.glitch.offset = offset_range.min\n",
    "\n",
    "t_offset = tqdm_notebook(total=int((offset_range.max-offset_range.min)/offset_range.step) + 1, leave=False,desc=\"Offset\")\n",
    "while scope.glitch.offset < offset_range.max:\n",
    "    scope.glitch.width = width_range.min\n",
    "    t_width = tqdm_notebook(total=int((width_range.max-width_range.min)/width_range.step), leave=False, desc=\"Width\")\n",
    "    while scope.glitch.width < width_range.max:\n",
    "        for j in tqdm_notebook(ext_range, leave=False, desc=\"Ext range\"):\n",
    "            scope.glitch.ext_offset = j\n",
    "            successes = 0\n",
    "            crashes = 0\n",
    "            for k in tnrange(sample_size, leave=False, desc=\"Attempt\"):\n",
    "                ret = do_glitch()\n",
    "                successes += ret[0]\n",
    "                crashes += ret[1]\n",
    "                \n",
    "            \n",
    "        glitches.append([scope.glitch.width, scope.glitch.offset, successes/sample_size, crashes/sample_size, j])\n",
    "        if successes > 0:\n",
    "            print([scope.glitch.width, scope.glitch.offset, successes/sample_size, crashes/sample_size, j])\n",
    "        scope.glitch.width += width_range.step\n",
    "        t_width.update()\n",
    "\n",
    "    scope.glitch.offset += offset_range.step\n",
    "    t_offset.update()\n",
    "    t_width.close()\n",
    "t_width.close()\n",
    "t_offset.close()\n",
    "scope.glitch.trigger_src = \"ext_single\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, sorting by success rate:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sort_glitch(glitch):\n",
    "    return glitch[2]\n",
    "\n",
    "glitches.sort(key=sort_glitch,reverse=True)\n",
    "for glitch in glitches:\n",
    "    print(glitch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Going Further"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There's a lot more you can do with this attack:\n",
    "\n",
    "* If you still weren't able to get any glitches, create an attack loop that scans a larger range of offsets and ranges.\n",
    "    * We also used a repeat of 1. You may find more success using a large repeat and a smaller width.\n",
    "* Glitching different instructions will produce different results. Try using your best glitch settings from the previous part and scanning ext offset ranges to produce different glitches\n",
    "    * During our attack loop, we only checked for glitches in the first number (40000). You may want to examine the other numbers for glitches as well\n",
    "    * Open the listing file (`.lss`) and view the assembly of the `glitch_infinite()` function. Can you explain the different glitch effects you saw?\n",
    "* Try using the glitch settings you found in this tutorial to glitch other functions in the `glitchsimple.c` file.\n",
    "\n",
    "Otherwise, we're done with the tutorial. You can now disconnect from the ChipWhisperer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.dis()\n",
    "target.dis()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the tutorial now finished, you should have some Vcc glitching experience under your belt. If you're interested in doing more Vcc glitching, you may want to try [Tutorial A9](https://wiki.newae.com/Tutorial_A9_Bypassing_LPC1114_Read_Protect) from the ChipWhisperer Wiki, which uses Vcc glitching to bypass code readout protection on an LPC1114 (requires an LPC1114 dev board). You may also want to try glitching some of the other functions in `glitchsimple.c`. If you have a Raspberry Pi, you can also attempt the attack described [here](https://wiki.newae.com/Tutorial_A3_VCC_Glitch_Attacks#Glitching_More_Advanced_Targets:_Raspberry_Pi) (though you'll need to transfer the steps from the old GUI over to Jupyter)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Test we got at least one success\n",
    "# Should be sorted by success rate, so just check first one\n",
    "success = glitches[0][2] > 0\n",
    "assert success, \"Failed to glitch target\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
